#ifndef __PLOG_H__
#define __PLOG_H__

#include <string>
#include "utils.h"
using namespace std;

typedef void (*ERROR_RECORDER)(int level , int& record_log_level, const string & error_str );

extern ERROR_RECORDER err_recorder;
extern int default_log_level;
extern int record_log_level;

/* Initialize the config of log system */
#define PLOG_INIT( INIT_RECORDER , REAL_RECORDER, RECORD_LOG_LEVEL, DEFAULT_LOG_LEVEL , LOG_FILE_PATH)		\
	do{							\
		INIT_RECORDER( RECORD_LOG_LEVEL , LOG_FILE_PATH );\
		default_log_level = (DEFAULT_LOG_LEVEL );	\
		record_log_level = (RECORD_LOG_LEVEL);		\
		err_recorder = ( REAL_RECORDER );		\
	}while(0)

/* Update the record log level */
#define PLOG_UPDATE_RECORD_LOG_LEVEL( RECORD_LOG_LEVEL )	\
	do{							\
		record_log_level = (RECORD_LOG_LEVEL);		\
	}while(0)

/* Update the default log level */
#define PLOG_UPDATE_DEFAULT_LOG_LEVEL( DEFAULT_LOG_LEVEL )	\
	do{							\
		default_log_level = (DEFAULT_LOG_LEVEL);	\
	}while(0)

/* Update the function pointer of log recorder */
#define PLOG_UPDATE_RECORDER( NEW_RECORDER )			\
	do{							\
		err_recorder = (NEW_RECORDER);			\
	}while(0)

/* The following are the operations of log printing */
#define PLOG_BEGIN						\
	do{							\
		if( err_recorder ){				\
			string _error_str;			\

#define PLOG_END( LOG_LEVEL )					\
			err_recorder( LOG_LEVEL, record_log_level , _error_str );	\
		}						\
	}while(0)

#define PLOG_ERR_APPEND( TYPE_STRING , ERROR_STRING )		\
			_error_str = ( TYPE_STRING );		\
			_error_str += (ERROR_STRING);		\
			_error_str += " -- ";			\
			_error_str.append(__FUNCTION__);	\
			_error_str += "():";			\
			_error_str += ValToString( __LINE__ );	\
			_error_str += " (";			\
			_error_str.append( __FILE__ );		\
			_error_str += ") ";			

/* print log with specified level */
#define LPLOG( LOG_LEVEL , ERR_STRING )				\
	PLOG_BEGIN						\
		_error_str = "INFO: ";				\
		_error_str += (ERR_STRING);			\
	PLOG_END( LOG_LEVEL )

/* print error log with specified level */
#define LEPLOG( LOG_LEVEL, ERROR_STRING )			\
	PLOG_BEGIN						\
	PLOG_ERR_APPEND( "ERRO: ",ERROR_STRING )		\
	PLOG_END( LOG_LEVEL )

/* print log with default level */
#define PLOG( ERROR_STRING )					\
	LPLOG( default_log_level , ERROR_STRING )

/* print log with record_log_level (always could be recorded )*/
#define APLOG( ERROR_STRING )					\
	LPLOG( record_log_level , ERROR_STRING )

/* print error log always */
#define EPLOG( ERROR_STRING )					\
	LEPLOG( record_log_level , ERROR_STRING )

/* print unknown type with specified level */
#define LPLOG_CATCH_UNKNOWN( LOG_LEVEL )			\
	LEPLOG( LOG_LEVEL , "Catch an unknown type exception " )
/* print unknown type catch log */
#define PLOG_CATCH_UNKNOWN()					\
	LPLOG_CATCH_UNKNOWN( record_log_level )


/*
		_error_str.append(__FUNCTION__":"__LINE__" ("__FILE__" )");	\
#ifdef RUN_IN_FOREGROUND
#define PLOG( ... ) 						\
	do{							\
		fprintf(stderr, __VA_ARGS__ );			\
		fflush(stderr);					\
	}while(0)
#else
#define PLOG( ... )				\
	do{					\
	}while(0)
#endif

// TEST PLOG
#ifdef TEST
#define TPLOG( ... )				\
	PLOG( __VA_ARGS__ );
#else
#define TEST_PLOG( ... )			
#endif
*/

#endif
